home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Compilers⁄Interps / kevoSource / image.c < prev    next >
Text File  |  1993-05-09  |  12KB  |  449 lines

  1. /* Kevo -- a prototype-based object-oriented language */
  2. /* (c) Antero Taivalsaari 1991-1993                   */
  3. /* Some parts (c) Antero Taivalsaari 1986-1988           */
  4. /* image.c: Image file management & decompilation       */
  5.  
  6. #include "global.h"
  7.  
  8. /*--------------------------------------------------------------------------*/
  9. /* Image file forward reference resolver operations */
  10.  
  11. SOLVE* LastRef = NIL;
  12.  
  13.  
  14. /* initResolver(): initialize the resolver list */
  15.  
  16. void initResolver()
  17. {
  18.   LastRef = NIL;
  19. }
  20.  
  21.  
  22. /* addForwardRef(): add a new name to resolver list */
  23.  
  24. void addForwardRef(name, location)
  25. char* name;
  26. int*  location;
  27. {
  28.   SOLVE* newRef = (SOLVE*)mymalloc(sizeof(SOLVE));
  29.  
  30. #ifdef DEBUG
  31.   printf("Adding forward reference: %s\n", name);
  32. #endif
  33.  
  34.   newRef->name = allocStrCpy(name);
  35.   newRef->loc  = location;
  36.   newRef->next = LastRef;  
  37.  
  38.   LastRef = newRef;
  39. }
  40.  
  41.  
  42. /* resolveRefs(): resolve all the previous references to a name  */
  43.  
  44. int resolveRefs(name, object)
  45. char*     name;
  46. int     object; 
  47. {
  48.   SOLVE* thisRef = LastRef;
  49.   SOLVE* prevRef = NIL;
  50.   SOLVE* tempRef;
  51.   int    count = 0;
  52.  
  53.   while(thisRef) {
  54.     if (strcmp(thisRef->name, name) == 0) {
  55.        *thisRef->loc = object;
  56.        count++;
  57.  
  58. #ifdef DEBUG
  59.     printf("Resolving forward reference: %s\n", name);
  60. #endif
  61.  
  62.        if (prevRef == NIL) LastRef = thisRef->next;
  63.        else prevRef->next = thisRef->next;
  64.  
  65.        tempRef = thisRef;
  66.        thisRef = thisRef->next;
  67.  
  68.        free(tempRef->name);
  69.        free(tempRef);
  70.     }
  71.     else {
  72.        prevRef = thisRef;
  73.        thisRef = thisRef->next;
  74.     }
  75.   }
  76.   return(count);
  77. }
  78.  
  79.  
  80. /* resolvedOk(): Are all the forward references already resolved? */
  81.  
  82. int resolvedOk()
  83. {
  84.   if (LastRef == NIL) return(TRUE);
  85.   else {
  86.     SOLVE* thisRef = LastRef; 
  87.     SOLVE* tempRef;
  88.  
  89.     while(thisRef) {
  90.     fprintf(stderr, "Unresolved reference '%s'.\n", thisRef->name); 
  91.  
  92.     tempRef = thisRef;
  93.     thisRef = thisRef->next;
  94.  
  95.         free(tempRef->name);
  96.         free(tempRef);
  97.     }
  98.  
  99.     LastRef = NIL;
  100.     return(FALSE);
  101.   }
  102. }
  103.  
  104.  
  105. /* ---------------------------------------------------------------------------------- */
  106.  
  107. /* openImage(): open image file */
  108.  
  109. void openImage(argc, argv)
  110. int   argc;
  111. char* argv[];
  112. {
  113.   if (argc > 1 ) {
  114.     if ((imgfile = fopen(argv[1], "r")) == NIL) {
  115.        printf("%s: cannot open image file \"%s\".\n", argv[0], argv[1]);
  116.        exit(1);
  117.     }
  118.   }
  119.   else {
  120.     if ((imgfile = fopen("kevo.img", "r")) == NIL) {
  121. /*       printf("%s: cannot open standard image file \"kevo.img\".\n", argv[0]); */
  122.         printf("Cannot find standard image file 'kevo.img'.\nCannot continue. Exiting.\n");
  123.        exit(1);
  124.     }
  125.  
  126.   } 
  127. }
  128.  
  129.  
  130. /* readComment: this operation is needed only in 'loadImage()'. */
  131. /* Its purpose is to read text until we encounter two right parentheses. */
  132.  
  133. void readComment()
  134. {
  135. paren:
  136.   while(fgetc(imgfile) != ')');
  137.   switch(fgetc(imgfile)) {
  138.     case ')': break;
  139.     default : goto paren;
  140.   }
  141. }
  142.  
  143.  
  144. /* loadImage(): load an image file to the system */
  145. /* xxx This code is rather ugly. Rewrite later. */
  146.  
  147. void loadImage()
  148. {
  149.   char    command[10];
  150.   char    name[64];
  151.   char    input[64];
  152.   int     number;
  153.  
  154.   PAIR*   newPair;
  155.  
  156.   PAIR*   pair;
  157.   PAIR*   prevPair;
  158.  
  159.   OBJECT* object;
  160.   int*    store;
  161.  
  162.   while(fscanf(imgfile, "%s", command) != EOF) {
  163.  
  164.         if (strcmp(command, "::") == 0) {
  165.               if (fscanf(imgfile, "%s %ld", name, &number) == EOF) goto corrupt;
  166.  
  167.                 /* xxx we shouldn't limit to 'rootContext' only. Change later. */
  168.  
  169.               /* printf("Defining: %s, number: %ld.\n", name, number); */
  170.  
  171.               newPair = addPair(rootContext, allocStrCpy(name), object = createClosure(number));
  172.               (void)resolveRefs(newPair->nfa, (int)newPair->ofa);
  173.               store = (int*)object->mfa;
  174.  
  175.                 prevPair = rootContext->firstPair;
  176.  
  177.               for ( ; number; number--) {
  178.                 if (fscanf(imgfile, "%s", input) == EOF) goto corrupt;
  179.  
  180.                    if (strcmp(input, "^^") == 0) {    /* String literal */
  181.                       char*   ptr;
  182.                     char    ch;
  183.  
  184.                    *store++ = (int)oStrLit;
  185.                     ptr = charbuffer; /* use the shared char buffer (global.c) */
  186.                     (void)fgetc(imgfile);   /* Read the extra blank */
  187.  
  188.                       /* Read text until we find two carats */
  189.                     carat:
  190.                       while((ch = fgetc(imgfile)) != '^') *ptr++ = ch;
  191.                       switch(ch = fgetc(imgfile)) {
  192.                           case '^': *ptr = 0; break;
  193.                           default : ungetc(ch, imgfile); goto carat;
  194.                       }
  195.  
  196.                     *store++ = (int)allocStrCpy(charbuffer); number--;
  197.                       /* printf("^^%s^^ ", charbuffer); */
  198.                       prevPair = rootContext->firstPair;
  199.                 }
  200.                 else {             /* Not a string literal */
  201.                     if (strcmp(input, "((") == 0) {
  202.                           readComment();
  203.                           number++;
  204.                           /* printf("Comment "); */
  205.                     }
  206.                     else {
  207.                           char*  temp;
  208.                           char** endPtr = &temp;
  209.                           int    result = strtol(input, endPtr, 0);
  210.                           if (!**endPtr) { 
  211.                               *store++ = result;       /* Number */
  212.                                 prevPair = rootContext->firstPair;
  213.                               /* printf("%ld ", result); */
  214.                             }
  215.                           else {
  216.                             if (pair = findPairInThis(rootContext, input)) {
  217.                                 *store++ = (int)pair->ofa;
  218.                                   /* printf("%s ", pair->nfa); */
  219.  
  220.                                 /* If '(=context)', allocate a context */
  221.                                   if (pair->ofa == oContext && prevPair->ofa != oLit) {
  222.  
  223.             /* xxx This must changed when image file loading is implemented in full detail */
  224.                                           fscanf(imgfile, "%s", input); number--;
  225.                                     if (strcmp(input, "DUMMY") == 0) 
  226.                                          *store++ = (int)dummyContext;
  227.                                        else *store++ = (int)lowCreateContext(); 
  228.                                   }
  229.  
  230.                                   prevPair = pair;
  231.                                }
  232.                             else {
  233.                                 addForwardRef(input, store++);  /* Add to unresolved */
  234.                                   prevPair = rootContext->firstPair;
  235.                                   /* printf("Unresolved: %s ", input); */
  236.                                }
  237.                           }
  238.                     }
  239.                 }
  240.               }
  241.               if (fscanf(imgfile, "%s %lx", command, &number) == EOF) goto corrupt;
  242.               if (strcmp(command, ";;") != 0) goto corrupt;
  243.               newPair->ffa = number;
  244.              /* printf("\nFlag field: %ld\n", number); */
  245.         }
  246.         else {  /* Allow comments outside of definitions, too */
  247.             if (strcmp(command, "((") != 0) goto corrupt;
  248.                else readComment();
  249.         }
  250.   }
  251.   if (!resolvedOk()) {
  252.           printf("Unresolved references in image file.\n");
  253.         printf("Cannot continue. Exiting.\n");
  254.         exit(1);
  255.   }
  256.   return;
  257.  
  258. corrupt:
  259.     printf("Image file structure corrupted near \"%s\".\n", name);
  260.     printf("Cannot continue. Exiting.\n");
  261.     exit(1);
  262. }
  263.  
  264.  
  265. /* initVariables(): initialize certain variables defined in image file
  266. /* so that primitive definitions can execute high-level definitions. */
  267. /* In particular, we want to invoke the high-level error routine */
  268. /* from primitives. */
  269. void initVariables()
  270. {
  271.   PAIR*  pair;
  272.   STORE* store;
  273.  
  274.   pair = findPairInThis(rootContext, "SystemRoot");
  275.   if (pair && pair->ofa && (store = pair->ofa->mfa)) {
  276.      /* 'SystemRoot' should point to 'rootContext'. Therefore, we */
  277.      /* free the automatically (by 'loadImage') allocated context */
  278.      free(store->pfa); 
  279.      store->pfa = (int*)rootContext;
  280.  
  281.      /* 'SystemRoot' must be made a full-fledged object */
  282.      /* by storing itself to its clone family (which is still empty) */
  283.      addToList(rootContext->cloneFamily, pair->ofa);
  284.   }
  285.   else goto error;
  286.  
  287.   pair = findPairInThis(rootContext, "Root");
  288.   if (pair && pair->ofa && (store = pair->ofa->mfa)) {
  289.      /* 'Root' should point to 'userContext'. Therefore, we */
  290.      /* free the automatically (by 'loadImage') allocated context */
  291.      free(store->pfa); 
  292.      store->pfa = (int*)userContext;
  293.      oUserRoot = pair->ofa;
  294.  
  295.      /* 'Root' must be made a full-fledged object */
  296.      /* by storing itself to its clone family (which is still empty) */
  297.      addToList(userContext->cloneFamily, oUserRoot);
  298.   }
  299.   else goto error;
  300.  
  301.   /* 'Up', 'firstTask, and 'latestTask' must initially point to the '(user)' task data area */
  302.   pair = findPairInThis(rootContext, "(user)");
  303.   if (pair && pair->ofa && pair->ofa->mfa)
  304.      firstTask = latestTask = up = (TASK**)pair->ofa;
  305.   else goto error;
  306.  
  307.   /* 'oBoot' must point to 'boot' */
  308.   pair = findPairInThis(rootContext, "boot");
  309.   if (pair && pair->ofa && pair->ofa->mfa)
  310.      oBoot = pair->ofa;
  311.   else goto error;
  312.     
  313.   /* 'oShell' must point to 'shell' */
  314.   /* This is needed for the debugger */
  315.   pair = findPairInThis(rootContext, "shell");
  316.   if (pair && pair->ofa && pair->ofa->mfa)
  317.      oShell = pair->ofa;
  318.   else goto error; 
  319.  
  320.   /* 'oError' must point to vector 'error' */
  321.   pair = findPairInThis(rootContext, "error");
  322.   if (pair && pair->ofa && pair->ofa->mfa)
  323.      oError = pair->ofa;
  324.   else {
  325. error: 
  326.      printf("Certain name(s) could not be found in image file.\n");
  327.      printf("Cannot continue. Exiting.\n");
  328.      exit(1);
  329.   }
  330. }
  331.  
  332.  
  333. /* ------------------------------------------------------------------------------- */
  334. /* Decompilation and image file generation */
  335.  
  336. /* decompile the definition of an object */
  337. void decompile(object)
  338. OBJECT* object;
  339. {
  340.   OBJECT** addr = (OBJECT**)object->mfa;
  341.   PAIR* thisPair;
  342.   PAIR* prevPair = rootContext->firstPair; /* xxx Whichever pair will do */
  343.   int count = object->sfa;
  344.  
  345.     ownPrintf(":: ");
  346.  
  347.     if (count) {    /* Not a primitive */
  348.  
  349.         if (count > 200) { 
  350.             ownPrintf("-- This definition is very large: decompiling only first 200 items -- "); 
  351.             ownCr();
  352.               count = 200;
  353.         } 
  354.  
  355.         for ( ; count > 0; count--, addr++) {
  356.             thisPair = findNameBackward(*addr);
  357.             if (thisPair) {
  358.                 if (strcmp(thisPair->nfa, "(\"lit)") == 0) {
  359.                     if (strcmp(prevPair->nfa, "(lit)") == 0) ownPrintf("\"lit) ");
  360.                      else {
  361.                            ownPrintf("^^ %s^^ ", (char*)*++addr); 
  362.                         count--;
  363.                     }
  364.                 }
  365.                 else ownPrintf("%s ", thisPair->nfa); 
  366.  
  367.                 prevPair = thisPair;
  368.             }
  369.             else {
  370.                 thisPair = findTypeForward(*addr);
  371.                 if (thisPair) {
  372.                     ownPrintf("%s:", thisPair->nfa);
  373.                     ownPrintf("%d ", (int)*addr);
  374.                 }
  375.                 else ownPrintf("%d ", (int)*addr);
  376.                 prevPair = rootContext->firstPair; /* Any pair will do */
  377.             }
  378.         }
  379.     }
  380.     else {    /* Is a primitive */
  381.         ownPrintf("(=primitive) %d ", (int)addr);
  382.     }
  383.     ownPrintf(";;");
  384.  
  385.     thisPair = findNameBackward(object);
  386.     if (thisPair && (thisPair->ffa & ImmedFlag)) ownPrintf(" immediate");
  387.     if (thisPair && (thisPair->ffa & HiddenFlag)) ownPrintf(" hidden");
  388.     ownCr();
  389. }
  390.  
  391.  
  392. /* generate an image of the whole system to outfile */
  393. /* (decompile the definitions of all the objects in their definition order) */
  394. /* xxx this needs to be reimplemented later */
  395.  
  396. void generateImage()
  397. {
  398.   /* xxx remove 'rootContext' later */
  399.   PAIR* pair = rootContext->firstPair;
  400.  
  401.   while (pair != NIL) {
  402.     OBJECT* object = pair->ofa;
  403.     OBJECT** addr = (OBJECT**)object->mfa;
  404.       PAIR* thisPair;
  405.     PAIR* prevPair = rootContext->firstPair; /* Any pair is ok */
  406.       int count = object->sfa;
  407.  
  408.     if (count) {    /* Not a primitive */
  409.  
  410.       ownPrintf(":: %s ", pair->nfa);
  411.       ownPrintf("%d ", count);
  412.  
  413.         for ( ; count--; addr++) {
  414.         thisPair = findNameForward(*addr);
  415.         if (thisPair) {
  416.           if (strcmp(thisPair->nfa, "(\"lit)") == 0) {
  417.                   if (strcmp(prevPair->nfa, "(lit)") == 0) 
  418.             ownPrintf("(\"lit) ");     /* (lit) ("lit) */
  419.              else {
  420.             ownPrintf("^^ %s^^ ", (char*)*++addr); 
  421.               count--;
  422.                   }
  423.           }
  424.           else ownPrintf("%s ", thisPair->nfa); 
  425.           prevPair = thisPair;
  426.         }
  427.         else {
  428.           ownPrintf("%d ", (int)*addr);
  429.           prevPair = rootContext->firstPair;    /* Any pair is ok */
  430.         }
  431.         }
  432.  
  433.       ownPrintf(";;");
  434.  
  435.         thisPair = findNameForward(object);
  436.       if (thisPair) {
  437.             ownPrintf(" %x", thisPair->ffa);
  438.           ownCr();
  439.       }
  440.     }
  441.     pair = pair->sfa;
  442.   }
  443. }
  444.  
  445.  
  446.  
  447.  
  448.  
  449.